a tool for shared writing and social publishing
at feature/analytics 76 lines 2.2 kB view raw
1import { z } from "zod"; 2import { makeRoute } from "../lib"; 3import type { Env } from "./route"; 4import { getIdentityData } from "actions/getIdentityData"; 5import { tinybird } from "lib/tinybird"; 6 7export type GetPublicationAnalyticsReturnType = Awaited< 8 ReturnType<(typeof get_publication_analytics)["handler"]> 9>; 10 11export const get_publication_analytics = makeRoute({ 12 route: "get_publication_analytics", 13 input: z.object({ 14 publication_uri: z.string(), 15 from: z.string().optional(), 16 to: z.string().optional(), 17 path: z.string().optional(), 18 }), 19 handler: async ( 20 { publication_uri, from, to, path }, 21 { supabase }: Pick<Env, "supabase">, 22 ) => { 23 const identity = await getIdentityData(); 24 if (!identity?.atp_did || !identity.entitlements?.publication_analytics) { 25 return { error: "unauthorized" as const }; 26 } 27 28 // Verify the user owns this publication 29 const { data: publication } = await supabase 30 .from("publications") 31 .select("*, publication_domains(*)") 32 .eq("uri", publication_uri) 33 .single(); 34 35 if (!publication || publication.identity_did !== identity.atp_did) { 36 return { error: "not_found" as const }; 37 } 38 39 const domain = publication.publication_domains?.[0]?.domain; 40 if (!domain) { 41 return { 42 result: { traffic: [], topReferrers: [], topPages: [] }, 43 }; 44 } 45 46 const [trafficResult, referrersResult, pagesResult] = await Promise.all([ 47 tinybird.publicationTraffic.query({ 48 domain, 49 ...(from ? { date_from: from } : {}), 50 ...(to ? { date_to: to } : {}), 51 ...(path ? { path } : {}), 52 }), 53 tinybird.publicationTopReferrers.query({ 54 domain, 55 ...(from ? { date_from: from } : {}), 56 ...(to ? { date_to: to } : {}), 57 ...(path ? { path } : {}), 58 limit: 10, 59 }), 60 tinybird.publicationTopPages.query({ 61 domain, 62 ...(from ? { date_from: from } : {}), 63 ...(to ? { date_to: to } : {}), 64 limit: 20, 65 }), 66 ]); 67 68 return { 69 result: { 70 traffic: trafficResult.data, 71 topReferrers: referrersResult.data, 72 topPages: pagesResult.data, 73 }, 74 }; 75 }, 76});